package cn.com.code.generator.thread;

import cn.com.do1.dsf.common.exception.RestException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Author: hongqi
 * @Date: 2020/7/7 14:18
 * @Description: 多线程切分执行器
 */
@Component
@Slf4j
public class MultiExecutor {
    private static final Logger logger = LoggerFactory.getLogger(MultiExecutor.class);
    //最大5个线程
    private static int maxThreadCount;
    //核心线程16个
    private static int corePoolSize;
    //最大线程池20
    private static int maximumPoolSize;


    @Value("${task.maxThreadCount:5}")
    public  void setMaxThreadCount(int maxThreadCount) {
        MultiExecutor.maxThreadCount = maxThreadCount;
    }
    @Value("${task.corePoolSize:16}")
    public  void setCorePoolSize(int corePoolSize) {
        MultiExecutor.corePoolSize = corePoolSize;
    }
    @Value("${task.maximumPoolSize:20}")
    public  void setMaximumPoolSize(int maximumPoolSize) {
        MultiExecutor.maximumPoolSize = maximumPoolSize;
    }

    /**
     * 执行方法(分批创建子线程)
     *
     * @param batches
     * @return
     */
    public static <T> Boolean exec(ThreadExecution execution, int batches, List notes) {

        if (notes == null || notes.size() == 0) {
            return true;
        }

        String currentUser = "user01";
        //创建一个线程池
        ExecutorService executorService = new ThreadPoolExecutor(corePoolSize
                , maximumPoolSize
                , 5
                , TimeUnit.SECONDS
                , new LinkedBlockingQueue<>()) {
            @Override
            public void beforeExecute(Thread t, Runnable r) {
                log.info("执行线程前=====");
            }
        };


        List<Future<Integer>> futures = new ArrayList<>();
        int noteSize = notes.size();
        if (noteSize < batches) {
            batches = 1;
        }
        int groupLen = noteSize  / batches;
        //分组超长最大线程限制，则设置分组数为10，计算分组集合尺寸
        if (batches > maxThreadCount) {
            batches = maxThreadCount;
            groupLen = noteSize  / batches;
        }
        logger.info("总长度：" + noteSize + "  分为：" + batches + "组  分组长度：" + groupLen);
        MultiEndFlag flag = new MultiEndFlag(batches);
        int startIndex, toIndex, maxIndex = notes.size();
        for (int i = 0; i < batches; i++) {
            startIndex = i * groupLen;
            toIndex = startIndex + groupLen;
            if (i == batches-1) {
                toIndex = maxIndex;
            }
            List<T> temp = notes.subList(startIndex, toIndex);
            if (temp == null || temp.size() == 0) {
                continue;
            }

            futures.add(executorService.submit(new DefaultExecutionTask(flag, temp, execution)));
        }
        flag.end();
//        logger.info("futures={}", JSONObject.toJSONString(futures));
        //子线程全部等待返回(存在异常，则直接抛向主线程)
        for (Future<Integer> future : futures) {
            try {
//                String name = Thread.currentThread().getName();
//                Long id = Thread.currentThread().getId();
//                logger.error("ThreaName={},ThreadId={},future.get()={},future.isDone()={}", name,id,future.get(),future.isDone());
                future.get();
            } catch (Exception e) {
                e.printStackTrace();
                //这里是输出的只有一个主线程
                logger.error("错误信息="+e.getMessage());
                String name = Thread.currentThread().getName();
                Long id = Thread.currentThread().getId();
                logger.error("线程执行异常，主线程MasterThreaName={}", name+";ThreadId="+id);
                throw new RestException(-1,"线程执行异常，主线程MasterThreaName={"+name+"},ThreadId={"+id+"}");
            }
        }
        //所有线程返回后，关闭线程池
        executorService.shutdown();
        return true;
    }


}
